﻿/***************************************************************************
 *		ElGee Google Chart API Helper
 *		Copyright(C) 2011 by Laurent Geffroy lgeffroy@gmail.com
 * 
 *		This program is free software; you can redistribute it and/or 
 *		modify it under the terms of the GNU General Public License as
 *		published by the Free Software Foundation; either version 2 of 
 *		the License, or (at your option) any later version.
 *		
 *		This program is distributed WITHOUT ANY WARRANTY; without even the
 *		implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
 *		See the GNU General Public License for more details.
 *	
 *      For particular licensing, please contact me at lgeffroy@gmail.com
 *****************************************************************************/

using System;
using System.ComponentModel;
using System.Text;
using System.Web.Script.Serialization;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace ElGee.Google.Charts
{
    /// <summary>
    /// Base Chart Control Class
    /// </summary>
    public class ChartControlBase : WebControl
    {
        /// <summary>
        /// Gets or sets the data.
        /// </summary>
        /// <value>The data.</value>
        [Bindable(false),
        Category("Appearance"),
        Description("The Data of the control")]
        public ChartDataSource Data
        {
            get
            {
                var s = ViewState["Data"] as ChartDataSource;
                return (s == null) ? null : s;
            }
            set
            {
                ViewState["Data"] = value;
            }
        }

        /// <summary>
        /// Gets or sets the data source address.
        /// </summary>
        /// <value>The data source address.</value>
        public Uri DataSourceAddress
        {
            get
            {
                string s = (string)ViewState["DataSourceAddress"];
                return (s == null) ? new Uri("") : new Uri(s);
            }
            set
            {
                ViewState["DataSourceAddress"] = value.ToString();
            }
        }

        /// <summary>
        /// Gets or sets the loader image.
        /// </summary>
        /// <value>The loader image.</value>
        [Bindable(true),
        Category("Appearance"),
        Description("The waiting image before loading the chart"), Themeable(true)]
        public String LoaderImage
        {
            get
            {
                string s = (string)ViewState["LoaderImage"];
                return (s == null) ? String.Empty : s;
            }
            set
            {
                ViewState["LoaderImage"] = value;
            }
        }

        [Bindable(true),
        Category("Appearance"),
        Description("The text to display while loading the chart"), Themeable(true)]
        public String LoaderImageText
        {
            get
            {
                string s = (string)ViewState["LoaderImageText"];
                return (s == null) ? "Loading" : s;
            }
            set
            {
                ViewState["LoaderImageText"] = value;
            }
        }

        /// <summary>
        /// Gets or sets the loader image CSS class.
        /// </summary>
        /// <value>The loader image CSS class.</value>
        [Bindable(true),
        Category("Appearance"),
        Description("The Class for the waiting image before loading the chart"), Themeable(true)]
        public String LoaderImageCssClass
        {
            get
            {
                string s = (string)ViewState["LoaderImageCssClass"];
                return (s == null) ? String.Empty : s;
            }
            set
            {
                ViewState["LoaderImageCssClass"] = value;
            }
        }

        /// <summary>
        /// Gets or sets the error CSS class.
        /// </summary>
        /// <value>The error CSS class.</value>
        [Bindable(true),
        Category("Appearance"),
        Description("The Class to display errors"), Themeable(true)]
        public String ErrorCssClass
        {
            get
            {
                string s = (string)ViewState["ErrorCssClass"];
                return (s == null) ? String.Empty : s;
            }
            set
            {
                ViewState["ErrorCssClass"] = value;
            }
        }


        /// <summary>
        /// Gets or sets the type of the chart.
        /// </summary>
        /// <value>The type of the chart.</value>
        protected string ChartType { get; set; }

        /// <summary>
        /// Gets or sets the options.
        /// </summary>
        /// <value>The options.</value>
        protected string Options { get; set; }

        /// <summary>
        /// Gets or sets the chart hash key.
        /// </summary>
        /// <value>The chart hash key.</value>
        protected string ChartHashKey { get; set; }

        /// <summary>
        /// Renders the control to the specified HTML writer.
        /// </summary>
        /// <param name="writer">The <see cref="T:System.Web.UI.HtmlTextWriter"/> object that receives the control content.</param>
        protected override void Render(HtmlTextWriter writer)
        {
            EnsureChildControls();
            base.Render(writer);
        }




        /// <summary>
        /// Renders the contents.
        /// </summary>
        /// <param name="output">The output.</param>
        protected override void RenderContents(HtmlTextWriter output)
        {
            EnsureChildControls();
            if (DesignMode)
            {
                output.Write("Google Chart Control (");
                output.Write(ChartType);
                output.Write(")");
                return;
            }

            output.Write("<div class='" + LoaderImageCssClass + "'><div>" + LoaderImageText + "</div>");
            if (LoaderImage != null)
                output.Write("<img src='" + ResolveClientUrl(LoaderImage) + "' alt='" + LoaderImageText + "'>");
            output.Write("</div>");

        }



        /// <summary>
        /// Called by the ASP.NET page framework to notify server controls that use composition-based implementation to create any child controls they contain in preparation for posting back or rendering.
        /// </summary>
        protected override void CreateChildControls()
        {
            Controls.Clear();
            base.CreateChildControls();

        }

        /// <summary>
        /// Renders the begin tag.
        /// </summary>
        /// <param name="output">The output.</param>
        public override void RenderBeginTag(HtmlTextWriter output)
        {
            output.AddAttribute(HtmlTextWriterAttribute.Class, this.CssClass);
            output.AddAttribute(HtmlTextWriterAttribute.Id, this.ClientID);
            output.RenderBeginTag(HtmlTextWriterTag.Div);

        }




        private const string GOOGLE_CORE = "google.load('visualization', '1', { packages: ['corechart'] });";
        private const string GOOGLE_INTENSITY = "google.load('visualization', '1', {packages:['intensitymap']});";
        private const string GOOGLE_GAUGE = "google.load('visualization', '1', {packages:['gauge']});";
        private const string GOOGLE_GEO = "google.load('visualization', '1', {packages:['geoMap']});";
        private const string GOOGLE_IMAGEAREA = "google.load('visualization', '1', {packages:['imageareachart']});";

        //        private const string JQUERY = @"$().ready(function () {
        //                                            $('#{0}').elgeeChart({ 
        //                                                datasourceUrl: {1},
        //                                                datasource: {2}, 
        //                                                chartOptions: {3},
        //                                                automaticStart: {4}, 
        //                                                type: 'lineChart'});
        //                                        });";

        /// <summary>
        /// Renders the HTML closing tag of the control into the specified writer. This method is used primarily by control developers.
        /// </summary>
        /// <param name="writer">A <see cref="T:System.Web.UI.HtmlTextWriter"/> that represents the output stream to render HTML content on the client.</param>
        public override void RenderEndTag(HtmlTextWriter writer)
        {
            writer.RenderEndTag();  // Closing Main Container
            bool automaticStart = false;


            string ds = "null";
            string url = "null";
            string options = "{}";
            if ((Data != null) && (Data.ItemsCount > 0))
            {

                ds = "jQuery.parseJSON('" + new JavaScriptSerializer().Serialize(Data) + "')";
                automaticStart = true;
            }
            else
            {
                if (DataSourceAddress != null)
                    url = "'" + DataSourceAddress.ToString() + "'";
            }

            if (!String.IsNullOrWhiteSpace(Options))
                options = Options;

            // Load the google Core package 
            writer.Write("<script language='javascript' type='text/javascript'>");

            switch (ChartType.ToLower())
            {
                case "intensitymap":
                    writer.Write(GOOGLE_INTENSITY);
                    break;
                case "gauge":
                    writer.Write(GOOGLE_GAUGE);
                    break;
                case "geomap":
                    writer.Write(GOOGLE_GEO);
                    break;
                case "imageareachart":
                    writer.Write(GOOGLE_IMAGEAREA);
                    break;
                default:
                    writer.Write(GOOGLE_CORE);
                    break;
            }
            


            StringBuilder sb = new StringBuilder();
            sb.Append("$().ready(function () {");
            sb.Append("$('#").Append(this.ClientID).Append("').elgeeChart({");
            sb.Append("datasourceUrl: ").Append(url).Append(",");
            sb.Append("datasource: ").Append(ds).Append(",");

            if (Options != null)
            {
                sb.Append("chartOptions: ").Append(options).Append(",");
                sb.Append("hashKey: '").Append(ChartHashKey).Append("',");
            }
            else
            {
                sb.Append("chartOptions: null,");
                sb.Append("hashKey: null,");
            }

            if (String.IsNullOrWhiteSpace(ErrorCssClass))
                sb.Append("errorCssClass: null,");
            else
                sb.Append("errorCssClass: '").Append(ErrorCssClass).Append("',");

            sb.Append("automaticStart: ").Append(automaticStart.ToString().ToLower()).Append(",");
            sb.Append("type: '").Append(ChartType).Append("'});");
            sb.Append("});");

            // Add the Jquery initialization
            writer.Write(sb.ToString());
            writer.Write("</script>");

        }

    }
}
